﻿using NLog;
using NLog.Config;
using System;
using System.Diagnostics;

namespace CoreHelper
{
    /// <summary>
    /// 日志NLog
    /// 需要使用nuget安装NLog.Database和NLog.Web.AspNetCore
    /// </summary>
    public static class LogHelper
    {
        //private static Logger logger = LogManager.GetLogger(""); //初始化日志类
        private static Logger logger = LogManager.GetCurrentClassLogger(); //初始化日志类

        #region 静态构造函数
        /// <summary>
        /// 静态构造函数
        /// </summary>
        static LogHelper()
        {
            #region 腾讯云托管发布时
            //LogManager.Configuration = new XmlLoggingConfiguration("/app/nlogConfig/nlog.config");
            #endregion

            #region IIS或者docker desktop打包测试时使用
            LogManager.Configuration = new XmlLoggingConfiguration(Environment.CurrentDirectory + "/nlogConfig/nlog.config");
            #endregion

        }
        #endregion

        #region Fatal,致命错误
        /// <summary>
        /// Fatal,致命错误
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Fatal(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Fatal, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region Error,错误
        /// <summary>
        /// Error,错误
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Error(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Error, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region Warn，警告
        /// <summary>
        /// Warn，警告
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Warn(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Warn, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region Info,普通日志，最常用
        /// <summary>
        /// Info,普通日志，最常用
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Info(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Info, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region Debug,调试
        /// <summary>
        /// Info,普通日志，最常用
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Debug(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Debug, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region Trace,跟踪
        /// <summary>
        /// Trace,跟踪
        /// </summary>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        public static void Trace(string sMessage, logsSource logssource = logsSource.其他, string CreateBy = "", Exception ex = null)
        {
            #region 定位日志位置
            StackTrace trace = new StackTrace();
            //获取是哪个类来调用的  
            string className = trace.GetFrame(1).GetMethod().DeclaringType.FullName;
            //获取方法名称
            string method = trace.GetFrame(1).GetMethod().Name;
            string sLogger = string.Format("{0}.{1}", className, method);
            #endregion

            WriteLog(LogLevel.Trace, sLogger, sMessage, logssource.ToString(), CreateBy, ex);
        }
        #endregion

        #region 通用写日志
        /// <summary>
        /// 通用写日志
        /// </summary>
        /// <param name="logLevel">日志等级,从低到高,Trace -》Debug-》 Information -》Warning-》 Error-》 Fatal</param>
        /// <param name="sLogger">日志位置</param>
        /// <param name="sMessage">日志信息</param>
        /// <param name="logssource">日志来源</param>
        /// <param name="CreateBy">创建人</param>
        /// <param name="ex">异常信息</param>
        private static void WriteLog(LogLevel logLevel, string sLogger, string sMessage, string logssource, string CreateBy, Exception ex = null)
        {
            #region 获取ip
            //HttpContextAccessor context = new HttpContextAccessor();
            //string IP = context.HttpContext?.Connection.RemoteIpAddress.ToString(); 
            #endregion

            #region 按月分表标记,每1个月1个表
            //string _monthflag = System.DateTime.Now.Month.ToString().PadLeft(2, '0');//按月分表标记            
            #endregion

            LogEventInfo ei = new LogEventInfo(logLevel, sLogger, sMessage);//日志级别，位置，消息
            ei.Properties["sLogger"] = sLogger;//位置
            ei.Properties["CreateBy"] = CreateBy;//创建人
            ei.Properties["LogSource"] = logssource;//来源
            //ei.Properties["monthflag"] = _monthflag;//自定义字段，nlog.config配置文件中使用方法${event-context:item=自定义字段}
            ei.Exception = ex;//异常
            switch (logLevel.ToString())
            {
                case "Fatal":
                    logger.Fatal(ei);
                    break;
                case "Error":
                    logger.Error(ei);
                    break;
                case "Warn":
                    logger.Warn(ei);
                    break;
                case "Info":
                    logger.Info(ei);
                    break;
                case "Debug":
                    logger.Debug(ei);
                    break;
                case "Trace":
                    logger.Trace(ei);
                    break;
            }


        }
        #endregion


        #region 日志来源
        /// <summary>
        /// 日志来源
        /// </summary>
        public enum logsSource
        {
            /// <summary>
            /// 微信
            /// </summary>
            微信 = 0,
            /// <summary>
            /// PC管理端
            /// </summary>
            PC管理端,
            /// <summary>
            /// BLL业务逻辑层
            /// </summary>
            BLL业务逻辑层,
            /// <summary>
            /// 名片api
            /// </summary>
            名片api,
            /// <summary>
            /// 金桔api
            /// </summary>
            金桔api,
            /// <summary>
            /// 其他
            /// </summary>
            其他
        }
        #endregion
    }



}